/*
 * Created by Jaren at 2022/10/28 17:42
 */
import 'dart:typed_data';

import 'package:binary/binary.dart';
import 'package:inmotion_protocol/base/vehicle_data.dart';
import 'package:inmotion_protocol/common/compact.dart';
import 'package:inmotion_protocol/common/product_model.dart';
import 'package:inmotion_protocol/common/product_version.dart';
import 'package:inmotion_protocol/lorin/bean/base/vehicle_real_time_info.dart';
import 'package:inmotion_protocol/lorin/bean/scooter/scooter_real_time_info.dart';
import 'package:inmotion_protocol/util/byte_util.dart';
import 'package:inmotion_protocol/util/device.dart';
import 'package:inmotion_protocol/util/version.dart';

class LE1AllRealTimeInfo extends ScooterAllRealTimeInfo {
  LE1AllRealTimeInfo(LE1RealTimeInfo realTimeInfo, LE1RealTimeState realTimeState, LE1RealTimeError realTimeError) : super(realTimeInfo, realTimeState, realTimeError);
}

class LE1VehicleSynthesizeRealTimeInfo extends VehicleSynthesizeRealTimeInfo<CommonVehicleRealTimeInfo, LE1RealTimeState, LE1RealTimeError> {
  LE1VehicleSynthesizeRealTimeInfo(CommonVehicleRealTimeInfo commonVehicleRealTimeInfo, LE1RealTimeState realTimeState, LE1RealTimeError realTimeError) : super(commonVehicleRealTimeInfo, realTimeState, realTimeError);
}

class LE1RealTimeInfo extends ScooterRealTimeInfo {
  Int8 motor1Temp = Int8.zero;
  Int8 motor2Temp = Int8.zero;

  LE1RealTimeInfo(ProductModel model, VersionWrapper version) : super(model, version);

  @override
  void initCompact() {
    if (VersionUtils.higherOrEquals(version.getAppVersionByDevice(DeviceUtils.lorinScooterBtDevice), '2.0.0')) {
      compact = V2LE1RealTimeInfoCompact();
    } else {
      compact = DefaultLE1RealTimeInfoCompact();
    }
  }
}

class DefaultLE1RealTimeInfoCompact extends Compact<LE1RealTimeInfo> {
  @override
  void fromBytes(LE1RealTimeInfo output, Uint8ClampedList bytes, int offset) {
    output.voltage = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.current = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.speed = ByteUtil.bytes2Int16Le(bytes, offset);
    offset += 2;
    output.mileage = ByteUtil.toUint16(ByteUtil.bytes2Uint16Le(bytes, offset).value * 10);
    offset += 2;
    output.remainderRange = ByteUtil.bytes2Uint16Le(bytes, offset);
    offset += 2;
    output.totalMileage = ByteUtil.bytes2Uint32Le(bytes, offset);
    offset += 4;
    output.batteryLevel = Uint16(ByteUtil.bytes2Uint8Le(bytes, offset).value * 100);
    offset++;
    output.mosTemp = ByteUtil.toInt8(bytes[offset]);
    offset++;
    output.motor1Temp = ByteUtil.toInt8(bytes[offset]);
    offset++;
    output.motor2Temp = ByteUtil.toInt8(bytes[offset]);
    output.motorTemp = output.motor2Temp;
    offset++;
    output.batteryTemp = ByteUtil.toInt8(bytes[offset]);
  }

  @override
  int length() {
    return 19;
  }
}

class V2LE1RealTimeInfoCompact extends DefaultLE1RealTimeInfoCompact {
  @override
  void fromBytes(LE1RealTimeInfo output, Uint8ClampedList bytes, int offset) {
    super.fromBytes(output, bytes, offset);

    /// V2版本单次里程单位正常，不需要做其他处理
    output.mileage = ByteUtil.bytes2Uint16Le(bytes, offset + 6);
  }
}

class LE1RealTimeState extends ScooterRealTimeState {
  LE1RealTimeState(ProductModel model, VersionWrapper version) : super(model, version);
}

class LE1RealTimeError extends ScooterRealTimeError {
  Uint4 motor1HallState = Uint4.zero;
  Uint4 motor2HallState = Uint4.zero;

  LE1RealTimeError(ProductModel model, VersionWrapper version) : super(model, version);

  @override
  void initCompact() {
    compact = DefaultLE1RealTimeErrorCompact();
  }
}

class DefaultLE1RealTimeErrorCompact extends Compact<LE1RealTimeError> {
  @override
  void fromBytes(LE1RealTimeError output, Uint8ClampedList bytes, int offset) {
    if (bytes.length < offset + length()) {
      return;
    }
    output.controllerComState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.motor1HallState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.motor2HallState = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.batteryState = ByteUtil.bitValue(bytes[offset], 3, 1);
    output.voltageState = ByteUtil.bitValue(bytes[offset], 4, 2);
    output.breakState = ByteUtil.bitValue(bytes[offset], 6, 1);
    output.throttleState = ByteUtil.bitValue(bytes[offset], 7, 1);
    offset++;

    output.hmicRxState = ByteUtil.bitValue(bytes[offset], 0, 1);
    output.mcRxState = ByteUtil.bitValue(bytes[offset], 1, 1);
    output.overMosTempState = ByteUtil.bitValue(bytes[offset], 2, 1);
    output.overMotorTempState = ByteUtil.bitValue(bytes[offset], 3, 1);
    output.overBatteryTempState = ByteUtil.bitValue(bytes[offset], 4, 1);
    output.mcHeartbeatState = ByteUtil.bitValue(bytes[offset], 5, 1);
    // 保留2bit
  }

  @override
  int length() {
    return 2;
  }
}
